/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#ifndef __3E657D23_24B1_426e_B8EC_01624FB2F171__
#define __3E657D23_24B1_426e_B8EC_01624FB2F171__

#include "../tools/head.h"

/////////////////////////////////////////////////////////////////////////////////////////
// 

namespace xos
{

    class socket_impl : public xos_stl::mem_item< release_impl< socket_impl >, thread_lock >,
        public i_socket
    {
    public:
        typedef release_impl< socket_impl > T;

    public:
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //

        static int get_xos_item_data( ITEM_DATA*& item_ptr );

    public:
        socket_impl();
        ~socket_impl();

    protected:
        sockaddr_storage m_local_addr;
        sockaddr_storage m_peer_addr;
        int m_hSocket;

    protected:
        int init_data();

	public:
		int init();
		int term();

    public:
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //
        
        // 
        // udp端口初始化
        // 
        int udp_init( const char * lpszLocalIp, uint16_t usLocalPort );

        // 
        // 返回值，为发送的字节数, -1表示失败
        // 
        int udp_send( const char * lpBuf, int nLen, const char * lpszToIp, uint16_t usToPort );

        // 
        // 返回值，为接收到的字节数, -1表示失败
        // 
        int udp_recv( char * lpBuf, int nLen, char * lpszFromIp, uint16_t * lpusFromPort );

        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //

        // 
        // tcp端口初始化
        // 
        int tcp_init( const char * lpszLocalIp, uint16_t usLocalPort, bool bBind );

        // 
        // accept
        // 
        int tcp_accept( i_socket ** ppv );

        // 
        // connect
        // 
        int tcp_connect( const char * lpszServerIp, uint16_t usServerPort );

        // 
        // tcp侦听
        // 
        int tcp_listen( int nNum );

        // 
        // 返回值，为发送的字节数, -1表示失败
        // 
        int tcp_send( const char * lpBuf, int nLen );

        // 
        // 返回值，为接收到的字节数, -1表示失败
        // 
        int tcp_recv( char * lpBuf, int nLen );

        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //

        // fill addr
        int fill_addr( uint16_t af, sockaddr_storage & ss_addr, const char * lpszIp, uint16_t uPort );
        int fill_addr( sockaddr_storage & ss_addr, const char * lpszIp, uint16_t uPort );

        int fill_ipv6( sockaddr_storage & ss_addr, const char * lpszIp, uint16_t uPort );
        int fill_ipv6_port( sockaddr_storage & ss_addr, uint16_t uPort );
        int fill_ipv6_ip( sockaddr_storage & ss_addr, const char * lpszIp );

        int fill_ipv4( sockaddr_storage & ss_addr, const char * lpszIp, uint16_t uPort );
        int fill_ipv4_port( sockaddr_storage & ss_addr, uint16_t uPort );
        int fill_ipv4_ip( sockaddr_storage & ss_addr, const char * lpszIp );
        
        // ipv4 map ipv6
        int ipv4_map_ipv6( char * lpszIpv6, int nSize, const char * lpszIpv4 );
        int get_ipv6_addr( sockaddr_storage & addr, const char * lpszIp );
        bool invalid_addr_name( const char * lpszName );

        // 
        // 解析域名或机器名
        // 
        int get_addr_by_name( const char * lpszName, sockaddr_storage * pIpv6Addr, sockaddr_storage * pIpv4Addr );

        // 
        // 从地址得到IP和端口
        // 
        int get_ip_port( sockaddr_storage & ss_addr, char * lpszIp, uint16_t * lpusPort );

        // 
        // 根据socket句柄得到IP和端口
        // 
        int get_local_addr( char * lpszIp, uint16_t * lpusPort );
        int get_peer_addr( char * lpszIp, uint16_t * lpusPort );

        // 
        // 取得socket句柄
        // 
        void set_socket( uint64_t ulSocket );
        uint64_t get_socket();

        // 
        // 设置异步/阻塞模式
        // 
        int set_async( bool bAsync );
        int set_nodelay();

        // 
        // 停止后续发送
        // 
        int shut_down( int how );

        // 
        // 关闭端口
        // 
        int close( int onoff, int linger );

        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // 

        // 
        // 保存地址
        // 
        void set_local_addr( sockaddr_storage & ss_addr );
        void set_peer_addr( sockaddr_storage & ss_addr );
        sockaddr_storage & get_local_addr();
        sockaddr_storage & get_peer_addr();

    protected:
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // 

        // 根据协议类型进行bind
        int bind_socket( uint16_t af, uint64_t hSocket, const char * lpszIp, uint16_t uPort );

        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // 

        // 
        // 得到本机名称和地址
        // 
        int get_name_and_ip( char * lpszName, char * lpszIpv6, char * lpszIpv4 );

    };
} // xos

#endif // __3E657D23_24B1_426e_B8EC_01624FB2F171__
